home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / disk utilities / backup / backup_restore / backup_src_v3.20.lha / SetupTape.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-24  |  36.9 KB  |  1,453 lines

  1. // SetupTape.c
  2. // 24 Aug 1996 14:40:53
  3.  
  4. #ifndef    BACKUP_INCLUDE
  5. #include "IncludeAll.c"
  6. #endif
  7. #include "Backup.h"
  8. #include "SetupTape.h"
  9. #include "Backup_proto.h"
  10. #include "TapeDrive.h"
  11. #include "BackupStrings.h"
  12.  
  13.  
  14. #define d(x)    ;
  15.  
  16.  
  17. #define    DEVICENAME_SIZE    40
  18. #define    DEFAULT_BUFMEMTYPE    (MEMF_24BITDMA | MEMF_PUBLIC)
  19. #define    DEFAULT_TAPENAME    "TAPE"
  20. #define    TESTBLOCK_COUNT        200
  21.  
  22.  
  23. static void STRender(ULONG ScaleX, ULONG ScaleY, UWORD OffsetX, UWORD OffsetY);
  24. static int OpenSTWindow(struct Window *Parent);
  25. void CloseSTWindow( void );
  26. static int HandleSTMsg(void);
  27. static void __interrupt HandleSTGadgetCallback(struct Hook *hook, struct Gadget *Gad, ULONG *Code);
  28. static void HandleSTGadget(struct Gadget *Gad, USHORT code);
  29. static void UseSTData(struct DiskFlags *Dsk);
  30. static void ScanSCSI(struct DiskFlags *Dsk);
  31. static void CheckTapeDrive(struct DiskFlags *Dsk);
  32. static void ClearTapeDrive(void);
  33. static void TestDrive(struct DiskFlags *Dsk);
  34. static void SetPropertyGadgets(const struct TapeFlags *Prop);
  35. static void STMessageText(const char *Text, ULONG MsgID, ...);
  36. static char *DecodeTapeError(struct DiskFlags *Dsk, char *Line);
  37. static BOOL DoTestTapeDrive(struct DiskFlags *Dsk);
  38. static long TestQFAAppend(struct DiskFlags *Dsk, unsigned char *DataBlock);
  39. static BOOL CreateMountFile(struct DiskFlags *Dsk);
  40. static BOOL WriteMountList(FILE *fd, const struct DiskFlags *Dsk);
  41. static BOOL MountTapeDrive(struct DiskFlags *Dsk);
  42. static void FindDsk(const char *Device, short Unit);
  43.  
  44.  
  45. extern struct ExecBase *SysBase;
  46.  
  47. // aus Backup_Window.c
  48. extern APTR vi;                // VisualInfo
  49. extern struct Screen *WBScreen;
  50.  
  51. // Variable aus Backup.c
  52. extern struct DiskFlags __far *Disks;
  53. extern unsigned short NDisk;        // Anzahl Einträge in Disks[]
  54. extern struct TextFont *myFont, *ScreenFont;
  55.  
  56. // aus FileSelect.c
  57. extern struct Window *activeWindow;    // das gerade aktive Backup-Window
  58. extern BOOL HelpActive;            // Online-Hilfe ist aktiv
  59. extern BOOL GadgetHelp;            // V39-GadgetHelp ist verfügbar
  60. extern ULONG BackupHelpGroup;        // Help Group
  61.  
  62. // aus Backup_Options.c / Backup_OptionsGadgets.h
  63. extern struct GenericGadgetImages GetFileGadgetImage;
  64.  
  65.  
  66. static struct BInputHandler *STInput = NULL;
  67.  
  68. static struct GadgetShort *STGadgetShort;    // Tabelle für Tasten-Kürzel
  69.  
  70. static MINLIST(STResourceList);
  71.  
  72. static struct Window         *STWnd = NULL;
  73. static struct Gadget         *STGList = NULL;
  74. static struct Gadget         *STGadgets[ST_CNT];
  75. static UWORD                  STLeft = 119;
  76. static UWORD                  STTop = 75;
  77. static UWORD                  STWidth = 503;
  78. static UWORD                  STHeight = 249;
  79.  
  80. static BOOL    CreateProtocol = TRUE;
  81.  
  82. static char ProductName[16+1];
  83. static char VendorName[8+1];
  84. static char RevisionName[4+1];
  85.  
  86. static struct Hook STGadgetShortHook =
  87.     {
  88.     { NULL },
  89.     HookEntry,
  90.     (ULONG (*)()) HandleSTGadgetCallback,
  91.     NULL,
  92.     };
  93.  
  94. static struct DiskFlags TapeDsk =
  95.     {
  96.     NULL, NULL,
  97.     { 0 },
  98.     "",
  99.     "scsi.device",
  100.     0,
  101.     };
  102.  
  103. static BOOL TapeDskOk = FALSE;
  104.  
  105. static char TapeDriveNames[8][40];
  106. static struct Node TapeDriveNodes[8];
  107. static struct MinList TapeDriveList;
  108. static short TapeDriveListCount;
  109.  
  110. static UWORD STGTypes[] =
  111.     {
  112.     GENERIC_KIND,
  113.     BUTTON_KIND,
  114.     BUTTON_KIND,
  115.     BUTTON_KIND,
  116.     STRING_KIND,
  117.     TEXT_KIND,
  118.     TEXT_KIND,
  119.     BUTTON_KIND,
  120.     BUTTON_KIND,
  121.     TEXT_KIND,
  122.     BUTTON_KIND,
  123.     CHECKBOX_KIND,
  124.     CHECKBOX_KIND,
  125.     CHECKBOX_KIND,
  126.     CHECKBOX_KIND,
  127.     CHECKBOX_KIND,
  128.     CHECKBOX_KIND,
  129.     CHECKBOX_KIND,
  130.     CHECKBOX_KIND,
  131.     CHECKBOX_KIND,
  132.     LISTVIEW_KIND,
  133.     TEXT_KIND,
  134.     CHECKBOX_KIND,
  135.     CHECKBOX_KIND,
  136.     BUTTON_KIND,
  137.     STRING_KIND,
  138.     };
  139.  
  140. static struct NewGadget STNGad[] =
  141.     {
  142.      12,   7,  24, 19, (UBYTE *) &GetFileGadgetImage, NULL,  GD_STDeviceFile,               0, NULL, NULL,
  143.     406, 215,  73, 19,    (UBYTE *) MSG_STCANCEL_GAD, NULL,      GD_STCancel,    PLACETEXT_IN, NULL, NULL,
  144.     308, 215,  73, 19,       (UBYTE *) MSG_STUSE_GAD, NULL,         GD_STUse,    PLACETEXT_IN, NULL, NULL,
  145.      12,  35, 174, 19,    (UBYTE *) MSG_SCANSCSI_GAD, NULL,    GD_STScanSCSI,    PLACETEXT_IN, NULL, NULL,
  146.      37,   8, 147, 17,                          NULL, NULL,  GD_STDeviceName,               0, NULL, NULL,
  147.      98,  81, 118, 16,       (UBYTE *) MSG_MODEL_GAD, NULL,       GD_STModel,  PLACETEXT_LEFT, NULL, NULL,
  148.      98, 100, 118, 16,    (UBYTE *) MSG_REVISION_GAD, NULL,    GD_STRevision,  PLACETEXT_LEFT, NULL, NULL,
  149.       4, 194, 174, 19,    (UBYTE *) MSG_GENMOUNT_GAD, NULL, GD_STCreateMount,    PLACETEXT_IN, NULL, NULL,
  150.       4, 216, 174, 19,       (UBYTE *) MSG_MOUNT_GAD, NULL,       GD_STMount,    PLACETEXT_IN, NULL, NULL,
  151.      98, 119, 118, 16,      (UBYTE *) MSG_VENDOR_GAD, NULL,      GD_STVendor,  PLACETEXT_LEFT, NULL, NULL,
  152.       3, 172, 174, 19,   (UBYTE *) MSG_TESTDRIVE_GAD, NULL,   GD_STTestDrive,    PLACETEXT_IN, NULL, NULL,
  153.     225,  78,  26, 11,       (UBYTE *) MSG_SCSI2_GAD, NULL,       GD_STSCSI2, PLACETEXT_RIGHT, NULL, NULL,
  154.     225,  90,  26, 11,         (UBYTE *) MSG_QFA_GAD, NULL,         GD_STQFA, PLACETEXT_RIGHT, NULL, NULL,
  155.     225, 102,  26, 11,   (UBYTE *) MSG_FASTSPACE_GAD, NULL,   GD_STFastSpace, PLACETEXT_RIGHT, NULL, NULL,
  156.     225, 114,  26, 11,      (UBYTE *) MSG_LOCATE_GAD, NULL,      GD_STLocate, PLACETEXT_RIGHT, NULL, NULL,
  157.     225, 126,  26, 11,   (UBYTE *) MSG_SPACEBACK_GAD, NULL,   GD_STSpaceBack, PLACETEXT_RIGHT, NULL, NULL,
  158.     359,  78,  26, 11,  (UBYTE *) MSG_PAGEFORMAT_GAD, NULL,  GD_STPageFormat, PLACETEXT_RIGHT, NULL, NULL,
  159.     359,  90,  26, 11,      (UBYTE *) MSG_INVEOT_GAD, NULL,   GD_STInvertEOT, PLACETEXT_RIGHT, NULL, NULL,
  160.     359, 102,  26, 11,   (UBYTE *) MSG_ERASELONG_GAD, NULL,   GD_STEraseLong, PLACETEXT_RIGHT, NULL, NULL,
  161.     359, 114,  26, 11,   (UBYTE *) MSG_QFAAPPEND_GAD, NULL,   GD_STQFAAppend, PLACETEXT_RIGHT, NULL, NULL,
  162.     198,   5, 288, 66,                          NULL, NULL,  GD_STTapeDrives,               0, NULL, NULL,
  163.       4, 151, 491, 16,                 NULL, NULL,    GD_STMessages,  PLACETEXT_LEFT, NULL, NULL,
  164.     257, 172,  26, 11,   (UBYTE*) MSG_CREATEPROT_GAD, NULL, GD_STCreateProtocol, PLACETEXT_RIGHT, NULL, NULL,
  165.     359, 126,  26, 11,     (UBYTE*) MSG_SPACEEOR_GAD, NULL,    GD_STSpaceEOR, PLACETEXT_RIGHT, NULL, NULL,
  166.     203, 215,  86, 20,         (UBYTE*) MSG_STOP_GAD, NULL,       GD_STAbort,    PLACETEXT_IN, NULL, NULL,
  167.     256, 189,  86, 17,   (UBYTE*) MSG_STTAPENAME_GAD, NULL,    GD_STTapeName, PLACETEXT_RIGHT, NULL, NULL,
  168.     };
  169.  
  170. static ULONG STGTags[] =
  171.     {
  172.     (TAG_DONE),
  173.     (GT_Underscore), '_', (TAG_DONE),
  174.     (GT_Underscore), '_', GA_Disabled, TRUE, (TAG_DONE),
  175.     (GT_Underscore), '_', (TAG_DONE),
  176.     (STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 50, (TAG_DONE),
  177.     (GTTX_Border), TRUE, (TAG_DONE),
  178.     (GTTX_Border), TRUE, (TAG_DONE),
  179.     (GT_Underscore), '_', (GA_Disabled), TRUE, (TAG_DONE),
  180.     (GT_Underscore), '_', (GA_Disabled), TRUE, (TAG_DONE),
  181.     (GTTX_Border), TRUE, (TAG_DONE),
  182.     (GT_Underscore), '_', (GA_Disabled), TRUE, (TAG_DONE),
  183.         GTCB_Scaled, TRUE,
  184.         (GT_Underscore), '_',
  185.     (TAG_DONE),
  186.         GTCB_Scaled, TRUE,
  187.         (GT_Underscore), '_',
  188.     (TAG_DONE),
  189.         GTCB_Scaled, TRUE,
  190.         (GT_Underscore), '_',
  191.     (TAG_DONE),
  192.         GTCB_Scaled, TRUE,
  193.         (GT_Underscore), '_',
  194.     (TAG_DONE),
  195.         GTCB_Scaled, TRUE,
  196.         (GT_Underscore), '_',
  197.     (TAG_DONE),
  198.         GTCB_Scaled, TRUE,
  199.         (GT_Underscore), '_',
  200.     (TAG_DONE),
  201.         GTCB_Scaled, TRUE,
  202.         (GT_Underscore), '_',
  203.     (TAG_DONE),
  204.         GTCB_Scaled, TRUE,
  205.         (GT_Underscore), '_',
  206.     (TAG_DONE),
  207.         GTCB_Scaled, TRUE,
  208.         (GT_Underscore), '_',
  209.     (TAG_DONE),
  210.     (GTLV_ShowSelected), NULL, (TAG_DONE),
  211.         (GTTX_Text), 0,
  212.         (GTTX_Border), TRUE,
  213.         GTTX_Justification, GTJ_CENTER,
  214.         GTTX_Clipped, TRUE,
  215.     (TAG_END),
  216.         GTCB_Scaled, TRUE,
  217.         (GT_Underscore), '_',
  218.     (TAG_END),
  219.         GTCB_Scaled, TRUE,
  220.         (GT_Underscore), '_',
  221.     (TAG_END),
  222.         (GT_Underscore), '_',
  223.         GA_Disabled, TRUE,
  224.     (TAG_END),
  225.         (GTST_String), (ULONG) DEFAULT_TAPENAME,
  226.         (GTST_MaxChars), 10,
  227.         (STRINGA_Justification), GACT_STRINGCENTER,
  228.         (STRINGA_ExitHelp), TRUE,
  229.         (GT_Underscore), '_',
  230.     (TAG_END),
  231.     };
  232.  
  233.  
  234. static void STRender(ULONG ScaleX, ULONG ScaleY, UWORD OffsetX, UWORD OffsetY)
  235. {
  236.     NewList((struct List *) &TapeDriveList);
  237.     TapeDriveListCount = 0;
  238.  
  239.     GT_SetGadgetAttrs(STGadgets[GDX_STTapeName],
  240.             STWnd, NULL,
  241.         GTST_String, TapeDsk.DOSName,
  242.         TAG_END);
  243.     GT_SetGadgetAttrs(STGadgets[GDX_STDeviceName],
  244.             STWnd, NULL,
  245.         GTST_String, TapeDsk.DeviceName,
  246.         TAG_END);
  247.     GT_SetGadgetAttrs(STGadgets[GDX_STCreateProtocol],
  248.             STWnd, NULL,
  249.             GTCB_Checked, CreateProtocol,
  250.             TAG_END);
  251.  
  252.     ClearTapeDrive();
  253.  
  254.     DrawBevelBox( STWnd->RPort, OffsetX + 220 * ScaleX/65535,
  255.                     OffsetY + 74 * ScaleY/65535,
  256.                     269 * ScaleX/65535,
  257.                     68  * ScaleY/65535,
  258.                     GT_VisualInfo, vi, GTBB_Recessed, TRUE, TAG_DONE );
  259.     DrawBevelBox( STWnd->RPort, OffsetX + 4 * ScaleX/65535,
  260.                     OffsetY + 2 * ScaleY/65535,
  261.                     491 * ScaleX/65535,
  262.                     65 * ScaleY/65535,
  263.                     GT_VisualInfo, vi, GTBB_Recessed, TRUE, TAG_DONE );
  264.     DrawBevelBox( STWnd->RPort, OffsetX + 4 * ScaleX/65535,
  265.                     OffsetY + 70 * ScaleY/65535,
  266.                     491 * ScaleX/65535,
  267.                     76 * ScaleY/65535,
  268.                     GT_VisualInfo, vi, GTBB_Recessed, TRUE, TAG_DONE );
  269. }
  270.  
  271.  
  272. static int OpenSTWindow(struct Window *Parent)
  273. {
  274.     struct NewWindow NewSTWnd;
  275.     struct Gadget    *g;
  276.     ULONG STScaleX, STScaleY;
  277.     UWORD STOffX, STOffY;
  278.     UWORD        ww, wh;
  279.     short n;
  280.  
  281.     NewSTWnd.LeftEdge = STLeft;
  282.     NewSTWnd.TopEdge = STTop;
  283.  
  284.     TapeDskOk = FALSE;
  285.  
  286.     // default-Wert für BufMemType
  287.     TapeDsk.DrvDat.BufMemType = DEFAULT_BUFMEMTYPE;
  288.  
  289.     strcpy(TapeDsk.DOSName, DEFAULT_TAPENAME);
  290.  
  291.     for (n=0; n<NDisk; n++)
  292.         {
  293.         if (Disks[n].TapeReq)
  294.             {
  295.             strcpy(TapeDsk.DOSName, Disks[n].DOSName);
  296.             strcpy(TapeDsk.DeviceName, Disks[n].DeviceName);
  297.             TapeDsk.Unit = Disks[n].Unit;
  298.             break;
  299.             }
  300.         }
  301.  
  302.     CreateGadgetShort(&STGadgetShort);
  303.  
  304.     CalcGadgetScale(WBScreen, ScreenFont, &STScaleX, &STScaleY, &STOffX, &STOffY, 8, 11);
  305.  
  306.     ww = STWidth * STScaleX/65535;
  307.     wh = STHeight * STScaleY/65535;
  308.  
  309.     g = CreateGadgetList(&STGList, ST_CNT,
  310.             WBScreen->Font,
  311.             STGTypes,
  312.             STNGad,
  313.             STGadgets,
  314.             STGTags,
  315.             STGadgetShort,
  316.             &STResourceList,
  317.             STScaleX, STScaleY,
  318.             STOffX, STOffY
  319.             );
  320.  
  321.     if (NULL == g)
  322.         {
  323.         alarm(GetString(MSG_CREATEGAD_FAILED), __FUNC__);
  324.         return( 2L );
  325.         }
  326.  
  327.     NewSTWnd.Width = ww + STOffX + WBScreen->WBorRight;
  328.     NewSTWnd.Height = wh + STOffY + WBScreen->WBorBottom;
  329.  
  330.     // STWnd über dem Mauszeiger zentrieren
  331.     CenterWindowMouse(Parent, &NewSTWnd);
  332.  
  333.     STWnd = OpenWindowTags( NULL,
  334.                 WA_Left,    NewSTWnd.LeftEdge,
  335.                 WA_Top,        NewSTWnd.TopEdge,
  336.                 WA_Width,    NewSTWnd.Width,
  337.                 WA_Height,    NewSTWnd.Height,
  338.                 WA_IDCMP,    IDCMP_GADGETUP | BUTTONIDCMP | STRINGIDCMP | INTEGERIDCMP 
  339.                     | TEXTIDCMP | IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY
  340.                     | IDCMP_ACTIVEWINDOW | IDCMP_VANILLAKEY | IDCMP_MENUHELP 
  341.                     | IDCMP_REFRESHWINDOW | IDCMP_GADGETHELP,
  342.                 WA_Flags,    WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
  343.                 WA_Gadgets,    STGList,
  344.                 WA_Title,    GetString(MSG_STWINDOW_TITLE),
  345.                 WA_PubScreen,    WBScreen,
  346.                 WA_AutoAdjust,    TRUE,
  347.                 WA_HelpGroup,    BackupHelpGroup,
  348.                 WA_MenuHelp,    TRUE,
  349.                 WA_NewLookMenus, TRUE,
  350.                 TAG_DONE);
  351.  
  352.     if (STWnd == NULL)
  353.         {
  354.         alarm(GetString(MSG_CANNOT_OPEN_WINDOW), __FUNC__, "STWnd");
  355.         return( 4L );
  356.         }
  357.  
  358.     GT_RefreshWindow( STWnd, NULL );
  359.  
  360.     STRender(STScaleX, STScaleY, STOffX, STOffY);
  361.  
  362.     STInput = AddBInputHandler(1l << STWnd->UserPort->mp_SigBit, HandleSTMsg);
  363.  
  364.     return( 0L );
  365. }
  366.  
  367.  
  368. void CloseSTWindow( void )
  369. {
  370.     RemBInputHandler(&STInput);
  371.  
  372.     if (STWnd)
  373.         SafeCloseWindow(&STWnd);
  374.  
  375.     if (STGList)
  376.         {
  377.         FreeGadgets( STGList );
  378.         STGList = NULL;
  379.         }
  380.  
  381.     FreeBResources(&STResourceList);
  382.     DestroyGadgetShort(&STGadgetShort);
  383. }
  384.  
  385.  
  386. void CleanupST(void)
  387. {
  388.     CloseSTWindow();
  389. }
  390.  
  391.  
  392. BOOL SetupTape(struct Window *Parent, struct DiskFlags *UnknownDsk)
  393. {
  394.     BOOL Result = TRUE;
  395.  
  396.     WindowBusy(Parent, TRUE);
  397.  
  398.     do    {
  399.         if (OpenSTWindow(Parent))
  400.             break;
  401.  
  402.         if (UnknownDsk)
  403.             {
  404.             // Wenn UnknownDsk != NULL, dann wird gezielt das dort beschriebene Laufwerk untersucht
  405.             strcpy(TapeDsk.DeviceName, UnknownDsk->DeviceName);
  406.             TapeDsk.Unit = UnknownDsk->Unit;
  407.             TapeDsk.DrvDat = UnknownDsk->DrvDat;
  408.  
  409.             WindowBusy(STWnd, TRUE);
  410.             ScanSCSI(&TapeDsk);
  411.  
  412.             TapeDsk.Unit = UnknownDsk->Unit;
  413.             GT_SetGadgetAttrs(STGadgets[GDX_STTapeDrives],
  414.                     STWnd, NULL,
  415.                 GTLV_Selected, TapeDsk.Unit,
  416.                 TAG_END);
  417.  
  418.             CheckTapeDrive(&TapeDsk);
  419.             WindowBusy(STWnd, FALSE);
  420.             }
  421.  
  422.         do    {
  423.             eingabe(0l);
  424.             } while (STWnd);
  425.         } while (0);
  426.  
  427.     WindowBusy(Parent, FALSE);
  428.  
  429.     return Result;
  430. }
  431.  
  432.  
  433. static int HandleSTMsg(void)
  434. {
  435.     struct IntuiMessage *msg;
  436.  
  437.     while (STWnd && (msg = GT_GetIMsg(STWnd->UserPort)) )
  438.         {
  439.         ULONG class;
  440.         USHORT code;
  441.         APTR Address;
  442.  
  443.         class = msg->Class;
  444.         code = msg->Code;
  445.         Address = msg->IAddress;
  446.  
  447.         GT_ReplyIMsg(msg);
  448.  
  449.         switch (class)
  450.             {
  451.         case IDCMP_ACTIVEWINDOW:
  452.             activeWindow = STWnd;
  453.             SetHelpPointer(activeWindow, HelpActive);
  454.             break;
  455.  
  456.         case IDCMP_GADGETHELP:
  457.             if (Address == NULL)
  458.                 {
  459.                 // Nicht über unserem Window
  460.                 }
  461.             else if (Address == STWnd)
  462.                 {
  463.                 // über dem Window
  464.                 CallHelp(HELPID_STWindow, TRUE);
  465.                 }
  466.             else
  467.                 CallHelp(((struct Gadget *) Address)->GadgetID, TRUE);
  468.             break;
  469.  
  470.         case IDCMP_MENUHELP:
  471.             break;
  472.  
  473.         case IDCMP_GADGETUP:
  474.             HandleSTGadget((struct Gadget *) Address, code);
  475.             break;
  476.  
  477.         case IDCMP_MENUPICK:
  478.             break;
  479.  
  480.         case IDCMP_VANILLAKEY:
  481.             HandleGadgetShort(STGadgetShort, STWnd, code, &STGadgetShortHook);
  482.             break;
  483.  
  484.         case IDCMP_RAWKEY:
  485.             d(printf("IDCMP_RAWKEY\n"));
  486.             if (GADCODE_HELP == code)
  487.                 ToggleHelp();
  488.             break;
  489.  
  490.         case IDCMP_CHANGEWINDOW:
  491.             STLeft = STWnd->LeftEdge;
  492.             STTop  = STWnd->TopEdge;
  493.             break;
  494.             }
  495.         }
  496.     return 0;
  497. }
  498.  
  499.  
  500. static void __interrupt HandleSTGadgetCallback(struct Hook *hook, struct Gadget *Gad, ULONG *Code)
  501. {
  502.     HandleSTGadget(Gad, (USHORT) *Code);
  503. }
  504.  
  505.  
  506. static void HandleSTGadget(struct Gadget *Gad, USHORT code)
  507. {
  508.     char DeviceName[DEVICENAME_SIZE];
  509.     char AcceptPattern[40];
  510.  
  511.     switch (Gad->GadgetID)
  512.         {
  513.     case GD_STUse:
  514.         CloseSTWindow();
  515.         UseSTData(&TapeDsk);
  516.         break;
  517.  
  518.     case GD_STCancel:
  519.         CloseSTWindow();
  520.         break;
  521.  
  522.     case GD_STScanSCSI:
  523.         GT_SetGadgetAttrs(STGadgets[GDX_STTestDrive],
  524.                 STWnd, NULL,
  525.             GA_Disabled, TRUE,
  526.             TAG_END);
  527.         GT_SetGadgetAttrs(STGadgets[GDX_STCreateMount],
  528.             STWnd, NULL,
  529.             GA_Disabled, TRUE,
  530.             TAG_END);
  531.         GT_SetGadgetAttrs(STGadgets[GDX_STMount],
  532.             STWnd, NULL,
  533.             GA_Disabled, TRUE,
  534.             TAG_END);
  535.         stccpy(TapeDsk.DeviceName, GADSTRING(STGadgets[GDX_STDeviceName]), sizeof(TapeDsk.DeviceName));
  536.         WindowBusy(STWnd, TRUE);
  537.         ScanSCSI(&TapeDsk);
  538.         WindowBusy(STWnd, FALSE);
  539.         break;
  540.  
  541.     case GD_STTapeDrives:
  542.         TapeDsk.Unit = TapeDriveNodes[code].ln_Pri;
  543.  
  544.         WindowBusy(STWnd, TRUE);
  545.         FindDsk(TapeDsk.DeviceName, TapeDsk.Unit); 
  546.         CheckTapeDrive(&TapeDsk);
  547.         WindowBusy(STWnd, FALSE);
  548.         break;
  549.  
  550.     case GD_STMount:
  551.         MountTapeDrive(&TapeDsk);
  552.         break;
  553.  
  554.     case GD_STCreateMount:
  555.         CreateMountFile(&TapeDsk);
  556.         break;
  557.  
  558.     case GD_STTestDrive:
  559.         TestDrive(&TapeDsk);
  560.         break;
  561.  
  562.     case GD_STDeviceFile:
  563.         ParsePatternNoCase((STRPTR) "#?.device", AcceptPattern, sizeof(AcceptPattern));
  564.  
  565.         if (StdFile(STWnd, GetString(MSG_SELECT_DEVICE), 
  566.                 "", DeviceName, sizeof(DeviceName),
  567.                 ASLFR_InitialDrawer, "DEVS:",
  568.                 ASLFR_InitialFile, TapeDsk.DeviceName,
  569.                 ASLFR_RejectIcons, TRUE,
  570.                 ASLFR_AcceptPattern, AcceptPattern,
  571.                 TAG_END))
  572.             {
  573.             GT_SetGadgetAttrs(STGadgets[GDX_STTestDrive],
  574.                     STWnd, NULL,
  575.                 GA_Disabled, TRUE,
  576.                 TAG_END);
  577.             GT_SetGadgetAttrs(STGadgets[GDX_STCreateMount],
  578.                 STWnd, NULL,
  579.                 GA_Disabled, TRUE,
  580.                 TAG_END);
  581.             GT_SetGadgetAttrs(STGadgets[GDX_STMount],
  582.                 STWnd, NULL,
  583.                 GA_Disabled, TRUE,
  584.                 TAG_END);
  585.  
  586.             stccpy(TapeDsk.DeviceName, FilePart(DeviceName), sizeof(TapeDsk.DeviceName));
  587.  
  588.             GT_SetGadgetAttrs(STGadgets[GDX_STDeviceName],
  589.                     STWnd, NULL,
  590.                 GTST_String, TapeDsk.DeviceName,
  591.                 TAG_END);
  592.             }
  593.         break;
  594.  
  595.     case GD_STCreateProtocol:
  596.         CreateProtocol = code;
  597.         break;
  598.         }
  599. }
  600.  
  601.  
  602. static void UseSTData(struct DiskFlags *Dsk)
  603. {
  604.     struct TapeDriveProperties DD;
  605.  
  606.     DD.Properties = Dsk->DrvDat.Properties;
  607.     stccpy(DD.Name, &Dsk->DrvDat.InquiryData[8], sizeof(DD.Name));
  608.  
  609.     WriteTapeDriveDataBase(&DD);
  610. }
  611.  
  612.  
  613. static void ScanSCSI(struct DiskFlags *Dsk)
  614. {
  615.     ClearTapeDrive();
  616.  
  617.     NewList((struct List *) &TapeDriveList);
  618.     TapeDriveListCount = 0;
  619.     TapeDskOk = FALSE;
  620.  
  621.     for (Dsk->Unit=0; Dsk->Unit<=7; Dsk->Unit++)
  622.         {
  623.         struct IOExtTD *TapeReq;
  624.  
  625.         STMessageText(NULL, MSG_CHECKING_SCSI_UNIT, Dsk->Unit);
  626.  
  627.         TapeReq = OpenDisk(Dsk, FALSE);
  628.         if (TapeReq)
  629.             {
  630.             Dsk->diskreq = TapeReq;
  631.             Dsk->TapeReq = AllocVec(sizeof(struct TapeIO), Dsk->DrvDat.BufMemType);
  632.             if (NULL == Dsk->TapeReq)
  633.                 {
  634.                 alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "TapeReq", sizeof(struct TapeIO));
  635.                 return;
  636.                 }
  637.             Dsk->TapeReq->DrvDat = &Dsk->DrvDat;
  638.             Dsk->TapeReq->Req = Dsk->diskreq;
  639.  
  640.             if (0 == TapeInquiry(Dsk->TapeReq))
  641.                 {
  642.                 if (DG_SEQUENTIAL_ACCESS == (Dsk->DrvDat.InquiryData[0] & 0x1f))
  643.                     {
  644.                     GT_SetGadgetAttrs(STGadgets[GDX_STTapeDrives],
  645.                             STWnd, NULL,
  646.                         GTLV_Labels, ~0,
  647.                         GTLV_Selected, ~0,
  648.                         TAG_END);
  649.  
  650.                     sprintf(TapeDriveNames[TapeDriveListCount],
  651.                             "%d: %28.28s", Dsk->Unit, &Dsk->DrvDat.InquiryData[8]);
  652.                     TapeDriveNodes[TapeDriveListCount].ln_Name = TapeDriveNames[TapeDriveListCount];
  653.                     TapeDriveNodes[TapeDriveListCount].ln_Type = NT_USER;
  654.                     TapeDriveNodes[TapeDriveListCount].ln_Pri = Dsk->Unit;
  655.                     AddTail((struct List *) &TapeDriveList, &TapeDriveNodes[TapeDriveListCount]);
  656.  
  657.                     TapeDriveListCount++;
  658.  
  659.                     GT_SetGadgetAttrs(STGadgets[GDX_STTapeDrives],
  660.                             STWnd, NULL,
  661.                         GTLV_Labels, &TapeDriveList,
  662.                         GTLV_Selected, ~0,
  663.                         TAG_END);
  664.                     }
  665.                 }
  666.  
  667.             FreeVec(Dsk->TapeReq);
  668.             Dsk->TapeReq = NULL;
  669.  
  670.             CloseDisk(Dsk, CDP_KeepTape);
  671.             }
  672.         }
  673.  
  674.     STMessageText("", 0);
  675. }
  676.  
  677.  
  678. static void CheckTapeDrive(struct DiskFlags *Dsk)
  679. {
  680.     struct IOExtTD *TapeReq;
  681.  
  682.     GT_SetGadgetAttrs(STGadgets[GDX_STUse],
  683.         STWnd, NULL,
  684.         GA_Disabled, TRUE,
  685.         TAG_END);
  686.     GT_SetGadgetAttrs(STGadgets[GDX_STCreateMount],
  687.         STWnd, NULL,
  688.         GA_Disabled, TRUE,
  689.         TAG_END);
  690.     GT_SetGadgetAttrs(STGadgets[GDX_STMount],
  691.         STWnd, NULL,
  692.         GA_Disabled, TRUE,
  693.         TAG_END);
  694.  
  695.     GT_SetGadgetAttrs(STGadgets[GDX_STTapeName],
  696.             STWnd, NULL,
  697.         GTST_String, TapeDsk.DOSName,
  698.         TAG_END);
  699.  
  700.     TapeReq = OpenDisk(Dsk, TRUE);
  701.     if (TapeReq)
  702.         {
  703.         Dsk->diskreq = TapeReq;
  704.         Dsk->TapeReq = AllocVec(sizeof(struct TapeIO), Dsk->DrvDat.BufMemType);
  705.         if (NULL == Dsk->TapeReq)
  706.             {
  707.             alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "TapeReq", sizeof(struct TapeIO));
  708.             return;
  709.             }
  710.         Dsk->TapeReq->DrvDat = &Dsk->DrvDat;
  711.         Dsk->TapeReq->Req = Dsk->diskreq;
  712.  
  713.         if (0 == TapeInquiry(Dsk->TapeReq))
  714.             {
  715.             WindowBusy(STWnd, TRUE);
  716.             TapeCheckDriveProperties(Dsk);
  717.             WindowBusy(STWnd, FALSE);
  718.  
  719.             GT_SetGadgetAttrs(STGadgets[GDX_STSCSI2],
  720.                     STWnd, NULL,
  721.                 GTCB_Checked, 2 == (Dsk->DrvDat.InquiryData[2] & 0x07),
  722.                 TAG_END);
  723.  
  724.             GT_SetGadgetAttrs(STGadgets[GDX_STPageFormat],
  725.                     STWnd, NULL,
  726.                 GTCB_Checked, Dsk->DrvDat.Properties.PageFormat,
  727.                 TAG_END);
  728.  
  729.             stccpy(ProductName, &Dsk->DrvDat.InquiryData[16], 16+1);
  730.             GT_SetGadgetAttrs(STGadgets[GDX_STModel],
  731.                     STWnd, NULL,
  732.                 GTTX_Text, ProductName,
  733.                 TAG_END);
  734.  
  735.             stccpy(VendorName, &Dsk->DrvDat.InquiryData[8], 8+1);
  736.             GT_SetGadgetAttrs(STGadgets[GDX_STVendor],
  737.                     STWnd, NULL,
  738.                 GTTX_Text, VendorName,
  739.                 TAG_END);
  740.  
  741.             stccpy(RevisionName, &Dsk->DrvDat.InquiryData[32], 4+1);
  742.             GT_SetGadgetAttrs(STGadgets[GDX_STRevision],
  743.                     STWnd, NULL,
  744.                 GTTX_Text, RevisionName,
  745.                 TAG_END);
  746.  
  747.             // USE freigeben wenn Laufwerk bekannt ist
  748.             GT_SetGadgetAttrs(STGadgets[GDX_STUse],
  749.                 STWnd, NULL,
  750.                 GA_Disabled, !Dsk->DrvDat.Properties.DriveKnown,
  751.                 TAG_END);
  752.  
  753.             // Create Mountlist freigeben wenn Laufwerk bekannt ist
  754.             GT_SetGadgetAttrs(STGadgets[GDX_STCreateMount],
  755.                 STWnd, NULL,
  756.                 GA_Disabled, !Dsk->DrvDat.Properties.DriveKnown,
  757.                 TAG_END);
  758.  
  759.             // MOUNT freigeben wenn Laufwerk bekannt ist
  760.             GT_SetGadgetAttrs(STGadgets[GDX_STMount],
  761.                 STWnd, NULL,
  762.                 GA_Disabled, !Dsk->DrvDat.Properties.DriveKnown,
  763.                 TAG_END);
  764.  
  765.             SetPropertyGadgets(&Dsk->DrvDat.Properties);
  766.             }
  767.  
  768.         FreeVec(Dsk->TapeReq);
  769.         Dsk->TapeReq = NULL;
  770.  
  771.         CloseDisk(Dsk, CDP_KeepTape);
  772.  
  773.         GT_SetGadgetAttrs(STGadgets[GDX_STTestDrive],
  774.                 STWnd, NULL,
  775.             GA_Disabled, FALSE,
  776.             TAG_END);
  777.         }
  778. }
  779.  
  780.  
  781. static void TestDrive(struct DiskFlags *Dsk)
  782. {
  783.     struct IOExtTD *TapeReq;
  784.  
  785.     TapeReq = OpenDisk(Dsk, TRUE);
  786.     if (TapeReq)
  787.         {
  788.         const char *Prompt;
  789.  
  790.         Dsk->diskreq = TapeReq;
  791.         Dsk->TapeReq = AllocVec(sizeof(struct TapeIO), Dsk->DrvDat.BufMemType);
  792.         if (NULL == Dsk->TapeReq)
  793.             {
  794.             alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "TapeReq", sizeof(struct TapeIO));
  795.             return;
  796.             }
  797.         Dsk->TapeReq->DrvDat = &Dsk->DrvDat;
  798.         Dsk->TapeReq->Req = Dsk->diskreq;
  799.  
  800.         WindowBusy(STWnd, TRUE);
  801.         TapeCheckDriveProperties(Dsk);
  802.         WindowBusy(STWnd, FALSE);
  803.  
  804.         GT_SetGadgetAttrs(STGadgets[GDX_STSCSI2],
  805.                 STWnd, NULL,
  806.             GTCB_Checked, 2 == (Dsk->DrvDat.InquiryData[2] & 0x07),
  807.             TAG_END);
  808.         GT_SetGadgetAttrs(STGadgets[GDX_STPageFormat],
  809.                 STWnd, NULL,
  810.             GTCB_Checked, 2 == (Dsk->DrvDat.InquiryData[2] & 0x07),
  811.             TAG_END);
  812.  
  813.         SetPropertyGadgets(&Dsk->DrvDat.Properties);
  814.  
  815.         TapeInitDrive(Dsk->TapeReq, Dsk);
  816.  
  817.         WindowBusy(STWnd, TRUE);
  818.         TapeTryLoadUnLoad(Dsk->TapeReq, TRUE);
  819.         WindowBusy(STWnd, FALSE);
  820.  
  821.         Prompt = GetString(TapeChangeState(Dsk->TapeReq) ? MSG_BEGINTEST_NOTAPE_PROMPT : MSG_BEGINTEST_PROMPT);
  822.  
  823.         if (yesno(STWnd, Prompt) == *GetString(MSG_YES_SHORT))
  824.             {
  825.             BOOL TestReady;
  826.  
  827.             WindowBusy(STWnd, TRUE);
  828.             TestReady = DoTestTapeDrive(Dsk);
  829.             WindowBusy(STWnd, FALSE);
  830.  
  831.             if (TestReady)
  832.                 {
  833.                 // "Use" Gadget einschalten wenn Test erfolgreich beendet.
  834.                 GT_SetGadgetAttrs(STGadgets[GDX_STUse],
  835.                         STWnd, NULL,
  836.                     GA_Disabled, FALSE,
  837.                     TAG_END);
  838.  
  839.                 GT_SetGadgetAttrs(STGadgets[GDX_STCreateMount],
  840.                     STWnd, NULL,
  841.                     GA_Disabled, FALSE,
  842.                     TAG_END);
  843.                 GT_SetGadgetAttrs(STGadgets[GDX_STMount],
  844.                     STWnd, NULL,
  845.                     GA_Disabled, FALSE,
  846.                     TAG_END);
  847.                 // "Test Drive" ausschalten
  848.                 GT_SetGadgetAttrs(STGadgets[GDX_STTestDrive],
  849.                         STWnd, NULL,
  850.                     GA_Disabled, TRUE,
  851.                     TAG_END);
  852.                 }
  853.             }
  854.  
  855.         STMessageText(NULL, MSG_UNLOADING_TAPE);
  856.         WindowBusy(STWnd, TRUE);
  857.         TapeTryLoadUnLoad(Dsk->TapeReq, FALSE);
  858.         WindowBusy(STWnd, FALSE);
  859.  
  860.         STMessageText("", 0);
  861.  
  862.         FreeVec(Dsk->TapeReq);
  863.         Dsk->TapeReq = NULL;
  864.  
  865.         CloseDisk(Dsk, CDP_KeepTape);
  866.         }
  867. }
  868.  
  869.  
  870. static void ClearTapeDrive(void)
  871. {
  872.     GT_SetGadgetAttrs(STGadgets[GDX_STUse],
  873.         STWnd, NULL,
  874.         GA_Disabled, TRUE,
  875.         TAG_END);
  876.     GT_SetGadgetAttrs(STGadgets[GDX_STCreateMount],
  877.         STWnd, NULL,
  878.         GA_Disabled, TRUE,
  879.         TAG_END);
  880.     GT_SetGadgetAttrs(STGadgets[GDX_STMount],
  881.         STWnd, NULL,
  882.         GA_Disabled, TRUE,
  883.         TAG_END);
  884.     GT_SetGadgetAttrs(STGadgets[GDX_STTapeDrives],
  885.             STWnd, NULL,
  886.         GTLV_Selected, ~0,
  887.         GTLV_Labels, ~0,
  888.         TAG_END);
  889.     GT_SetGadgetAttrs(STGadgets[GDX_STSCSI2],
  890.             STWnd, NULL,
  891.         GTCB_Checked, FALSE,
  892.         TAG_END);
  893.     GT_SetGadgetAttrs(STGadgets[GDX_STPageFormat],
  894.             STWnd, NULL,
  895.         GTCB_Checked, FALSE,
  896.         TAG_END);
  897.     GT_SetGadgetAttrs(STGadgets[GDX_STModel],
  898.             STWnd, NULL,
  899.         GTTX_Text, "",
  900.         TAG_END);
  901.     GT_SetGadgetAttrs(STGadgets[GDX_STVendor],
  902.             STWnd, NULL,
  903.         GTTX_Text, "",
  904.         TAG_END);
  905.     GT_SetGadgetAttrs(STGadgets[GDX_STRevision],
  906.             STWnd, NULL,
  907.         GTTX_Text, "",
  908.         TAG_END);
  909. }
  910.  
  911.  
  912.  
  913. static void SetPropertyGadgets(const struct TapeFlags *Prop)
  914. {
  915.     GT_SetGadgetAttrs(STGadgets[GDX_STQFA],
  916.             STWnd, NULL,
  917.         GTCB_Checked, Prop->canQFA,
  918.         TAG_END);
  919.     GT_SetGadgetAttrs(STGadgets[GDX_STFastSpace],
  920.             STWnd, NULL,
  921.         GTCB_Checked, Prop->FastSpace,
  922.         TAG_END);
  923.     GT_SetGadgetAttrs(STGadgets[GDX_STLocate],
  924.             STWnd, NULL,
  925.         GTCB_Checked, Prop->canLocate,
  926.         TAG_END);
  927.     GT_SetGadgetAttrs(STGadgets[GDX_STSpaceBack],
  928.             STWnd, NULL,
  929.         GTCB_Checked, Prop->SpaceBack,
  930.         TAG_END);
  931.     GT_SetGadgetAttrs(STGadgets[GDX_STInvertEOT],
  932.             STWnd, NULL,
  933.         GTCB_Checked, Prop->InvertEOT,
  934.         TAG_END);
  935.     GT_SetGadgetAttrs(STGadgets[GDX_STEraseLong],
  936.             STWnd, NULL,
  937.         GTCB_Checked, Prop->EraseLONG,
  938.         TAG_END);
  939.     GT_SetGadgetAttrs(STGadgets[GDX_STQFAAppend],
  940.             STWnd, NULL,
  941.         GTCB_Checked, Prop->AppendQFA,
  942.         TAG_END);
  943.     GT_SetGadgetAttrs(STGadgets[GDX_STSpaceEOR],
  944.             STWnd, NULL,
  945.         GTCB_Checked, Prop->SpaceEOR,
  946.         TAG_END);
  947. }
  948.  
  949.  
  950. static void STMessageText(const char *Text, ULONG MsgID, ...)
  951. {
  952.     char Line[120];
  953.     va_list args;
  954.  
  955.     va_start(args, MsgID);
  956.  
  957.     if (NULL == STWnd)
  958.         return;
  959.  
  960.     if (NULL == Text)
  961.         Text = GetString(MsgID);
  962.  
  963.     vsprintf(Line, Text, args);
  964.  
  965.     GT_SetGadgetAttrs(STGadgets[GDX_STMessages],
  966.         STWnd, NULL,
  967.         GTTX_Text, Line,
  968.         TAG_END);
  969.  
  970.     va_end(args);
  971. }
  972.  
  973.  
  974. static char *DecodeTapeError(struct DiskFlags *Dsk, char *Line)
  975. {
  976.     static const long SKMessages[] =
  977.         {
  978.         MSG_SK_NOSENSE, MSG_SK_RECOVEREDERROR, MSG_SK_NOTREADY, MSG_SK_MEDIUMERROR,
  979.         MSG_SK_HARDWAREERROR, MSG_SK_ILLEGALREQUEST, MSG_SK_UNITATTENTION, MSG_SK_DATAPROTECT,
  980.         MSG_SK_BLANKCHECK, MSG_SK_VENDORSPECIFIC, MSG_SK_COPYABORTED,
  981.         MSG_SK_ABORTEDCOMMAND, MSG_SK_EQUAL, MSG_SK_VOLUMEOVERFLOW, MSG_SK_MISCOMPARE,
  982.         MSG_SK_RESERVED
  983.         };
  984.     unsigned char SenseKey, ASC, ASCQ;
  985.  
  986.     SenseKey = Dsk->TapeReq->Sense[2] & 0x0f;
  987.     ASC  = Dsk->TapeReq->Cmd.scsi_SenseLength > 12 ? Dsk->TapeReq->Sense[12] : 0;
  988.     ASCQ = Dsk->TapeReq->Cmd.scsi_SenseLength > 13 ? Dsk->TapeReq->Sense[13] : 0;
  989.  
  990.     sprintf(Line, GetString(MSG_TAPE_ERRMSG),
  991.             Dsk->TapeReq->Cmd.scsi_Status,
  992.             Dsk->TapeReq->Sense[2], GetString(SKMessages[SenseKey]),
  993.             ASC, ASCQ
  994.             );
  995.  
  996.     return Line;
  997. }
  998.  
  999.  
  1000. static BOOL DoTestTapeDrive(struct DiskFlags *Dsk)
  1001. {
  1002.     unsigned long MaxBlock, MinBlock;
  1003.     unsigned char *DataBlock;
  1004.     char Line[120];
  1005.     short Result, n;
  1006.  
  1007.     if (TapeChangeState(Dsk->TapeReq))
  1008.         {
  1009.         // kein Band im Laufwerk
  1010.         return FALSE;
  1011.         }
  1012.  
  1013.     if (0 != TapeProtStatus(Dsk->TapeReq))
  1014.         {
  1015.         // Pech gehabt - Band ist schreibgeschützt
  1016.         alarm(GetString(MSG_TAPE_WRITEPROTECTED));
  1017.         return FALSE;
  1018.         }
  1019.  
  1020.     // ggf. ProtFile zu diesem Band löschen
  1021.     CheckOldProtFile(Dsk);
  1022.  
  1023.     // QFA testen
  1024.     STMessageText(NULL, MSG_QFA_PROGRESS);
  1025.     Dsk->DrvDat.Properties.canQFA = 1;
  1026.     Result = TapeInitQFA(Dsk->TapeReq, TRUE);
  1027.     if (CreateProtocol)
  1028.         {
  1029.         PostError(TRUE, MSGPRI_Info, 
  1030.             GetString(MSG_QFA_RESULT),
  1031.             Result ? DecodeTapeError(Dsk, Line) : GetString(MSG_STRESULT_OK));
  1032.         }
  1033.     STMessageText(NULL, MSG_QFA_RESULT,
  1034.         Result ? GetString(MSG_STRESULT_FAIL) : GetString(MSG_STRESULT_OK));
  1035.     SetPropertyGadgets(&Dsk->DrvDat.Properties);
  1036.     Delay(100);
  1037.  
  1038.  
  1039.     // ERASE long/short testen
  1040.     // zuerst ERASE SHORT versuchen
  1041.     STMessageText(NULL, MSG_ERASE_PROGRESS, "");
  1042.     Dsk->DrvDat.Properties.EraseLONG = 0;
  1043.     Result = TapeErase(Dsk->TapeReq);
  1044.     if (Result)
  1045.         {
  1046.         // ERASE SHORT hat nicht geklappt
  1047.         // jetzt mit ERASE LONG versuchen
  1048.         if (CreateProtocol)
  1049.             PostError(TRUE, MSGPRI_Info, GetString(MSG_ERASESHORT_FAIL), DecodeTapeError(Dsk, Line));
  1050.         }
  1051.     if (!Result)
  1052.         TapeProtStatus(Dsk->TapeReq);    // warten bis ERASE fertig
  1053.     if (CreateProtocol)
  1054.         {
  1055.         PostError(TRUE, MSGPRI_Info, GetString(MSG_ERASE_RESULT),
  1056.             Dsk->DrvDat.Properties.EraseLONG ? "LONG" : "",
  1057.             Result ? DecodeTapeError(Dsk, Line) : GetString(MSG_STRESULT_OK));
  1058.         }
  1059.     STMessageText(NULL, MSG_ERASE_RESULT,
  1060.         Dsk->DrvDat.Properties.EraseLONG ? "LONG" : "",
  1061.         Result ? GetString(MSG_STRESULT_FAIL) : GetString(MSG_STRESULT_OK));
  1062.     SetPropertyGadgets(&Dsk->DrvDat.Properties);
  1063.     Delay(100);
  1064.  
  1065.  
  1066.     STMessageText(NULL, MSG_REWINDING);
  1067.     TapeRewind(Dsk->TapeReq);
  1068.  
  1069.     // Blocklänge festlegen (ideal: 512 Bytes)
  1070.     Result = TapeReadBlockLimits(Dsk->TapeReq, &MinBlock, &MaxBlock);
  1071.     if (0 == Result)
  1072.         {
  1073.         if (CreateProtocol)
  1074.             PostError(TRUE, MSGPRI_Info, GetString(MSG_READBLOCKLIMITS_OK), MinBlock, MaxBlock);
  1075.  
  1076.         Dsk->DrvDat.BlockSize = MaxBlock > 512ul ? 512ul : MaxBlock;
  1077.         Dsk->DrvDat.BlockSize = Dsk->DrvDat.BlockSize > MinBlock ? Dsk->DrvDat.BlockSize : MinBlock;
  1078.         }
  1079.     else
  1080.         {
  1081.         if (CreateProtocol)
  1082.             PostError(TRUE, MSGPRI_Info, GetString(MSG_READBLOCKLIMITS_FAIL), DecodeTapeError(Dsk, Line));
  1083.         Dsk->DrvDat.BlockSize = 512l;
  1084.         }
  1085.  
  1086.     STMessageText(NULL, MSG_BLOCKSIZE_SELECTED, Dsk->DrvDat.BlockSize);
  1087.  
  1088.     DataBlock = AllocVec(Dsk->DrvDat.BlockSize, Dsk->DrvDat.BufMemType);
  1089.     if (NULL == DataBlock)
  1090.         {
  1091.         alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "DataBlock", Dsk->DrvDat.BlockSize);
  1092.         return FALSE;
  1093.         }
  1094.  
  1095.  
  1096.     STMessageText(NULL, MSG_WRITING_BLOCKS, TESTBLOCK_COUNT);
  1097.     for (n=Result=0; !Result && n<TESTBLOCK_COUNT; n++)
  1098.         {
  1099.         memset(DataBlock, n, Dsk->DrvDat.BlockSize);
  1100.         Result = TapeWrite(Dsk->TapeReq, DataBlock, Dsk->DrvDat.BlockSize);
  1101.         if (Result && CreateProtocol)
  1102.             PostError(TRUE, MSGPRI_Info, GetString(MSG_TAPEWRITE_FAIL), DecodeTapeError(Dsk, Line));
  1103.         }
  1104.     if (CreateProtocol)
  1105.         {
  1106.         PostError(TRUE, MSGPRI_Info, GetString(MSG_TAPEWRITE_RESULT), n, TESTBLOCK_COUNT,
  1107.             Result ? GetString(MSG_STRESULT_FAIL) : GetString(MSG_STRESULT_OK));
  1108.         }
  1109.     STMessageText(NULL, MSG_TAPEWRITE_RESULT, n, TESTBLOCK_COUNT,
  1110.         Result ? GetString(MSG_STRESULT_FAIL) : GetString(MSG_STRESULT_OK));
  1111.     SetPropertyGadgets(&Dsk->DrvDat.Properties);
  1112.     Delay(100);
  1113.  
  1114.  
  1115. //    Result = WriteFileMarks(Dsk->TapeReq, 1, FALSE);
  1116.  
  1117.     STMessageText(NULL, MSG_REWINDING);
  1118.     TapeRewind(Dsk->TapeReq);
  1119.  
  1120.  
  1121.     Dsk->DrvDat.Properties.SpaceEOR = 1;
  1122.     STMessageText(NULL, MSG_SPACE_EOR_PROGRESS);
  1123.     Result = TapeSpace(Dsk->TapeReq, 0, 3);
  1124.     if (CreateProtocol)
  1125.         {
  1126.         PostError(TRUE, MSGPRI_Info, GetString(MSG_SPACE_EOR_RESULT),
  1127.             Result ? DecodeTapeError(Dsk, Line) : GetString(MSG_STRESULT_OK));
  1128.         }
  1129.     if (Result)
  1130.         Dsk->DrvDat.Properties.SpaceEOR = 0;
  1131.     STMessageText(NULL, MSG_SPACE_EOR_RESULT,
  1132.         Result ? GetString(MSG_STRESULT_FAIL) : GetString(MSG_STRESULT_OK));
  1133.     SetPropertyGadgets(&Dsk->DrvDat.Properties);
  1134.     Delay(100);
  1135.  
  1136.  
  1137.     if (!Dsk->DrvDat.Properties.SpaceEOR)
  1138.         {
  1139.         // Band auf Block 50 stellen wenn "Space To End Of Recording" nicht geklappt hat
  1140.         // damit "Space Back" probiert werden kann!
  1141.         TapeRewind(Dsk->TapeReq);
  1142.         TapeSpace(Dsk->TapeReq, 50, 0);
  1143.         }
  1144.  
  1145.  
  1146.     // SPACE Backwards testen
  1147.     STMessageText(NULL, MSG_SPACEBACK_PROGRESS, 5);
  1148.     Dsk->DrvDat.Properties.SpaceBack = 1;
  1149.     Result = TapeSpace(Dsk->TapeReq, -5, 0);
  1150.     if (Result)
  1151.         Dsk->DrvDat.Properties.SpaceBack = 0;
  1152.     if (CreateProtocol)
  1153.         {
  1154.         PostError(TRUE, MSGPRI_Info, GetString(MSG_SPACEBACK_RESULT), 5,
  1155.             Result ? DecodeTapeError(Dsk, Line) : GetString(MSG_STRESULT_OK));
  1156.         }
  1157.     STMessageText(NULL, MSG_SPACEBACK_RESULT, 5, 
  1158.         Result ? GetString(MSG_STRESULT_FAIL) : GetString(MSG_STRESULT_OK));
  1159.     SetPropertyGadgets(&Dsk->DrvDat.Properties);
  1160.     Delay(100);
  1161.  
  1162.  
  1163.     STMessageText(NULL, MSG_REWINDING);
  1164.     TapeRewind(Dsk->TapeReq);
  1165.  
  1166.  
  1167.     STMessageText(NULL, MSG_LOCATE_PROGRESS, TESTBLOCK_COUNT/2);
  1168.     Dsk->DrvDat.Properties.canLocate = 1;
  1169.     Result = TapeLocate(Dsk->TapeReq, 50);
  1170.     if (Result)
  1171.         Dsk->DrvDat.Properties.canLocate = 0;
  1172.     if (CreateProtocol)
  1173.         {
  1174.         PostError(TRUE, MSGPRI_Info, GetString(MSG_LOCATE_RESULT), TESTBLOCK_COUNT/2,
  1175.             Result ? DecodeTapeError(Dsk, Line) : GetString(MSG_STRESULT_OK));
  1176.         }
  1177.     STMessageText(NULL, MSG_LOCATE_RESULT, TESTBLOCK_COUNT/2, 
  1178.         Result ? GetString(MSG_STRESULT_FAIL) : GetString(MSG_STRESULT_OK));
  1179.     SetPropertyGadgets(&Dsk->DrvDat.Properties);
  1180.     Delay(100);
  1181.  
  1182.  
  1183.     // Testen ob QFA bei Append klappt
  1184.     if (Dsk->DrvDat.Properties.canQFA && Dsk->DrvDat.Properties.SpaceEOR)
  1185.         {
  1186.         Dsk->DrvDat.Properties.AppendQFA = 1;
  1187.  
  1188.         STMessageText(NULL, MSG_QFAAPPEND_PROGRESS);
  1189.         Result = TestQFAAppend(Dsk, DataBlock);
  1190.         STMessageText(NULL, MSG_QFAAPPEND_RESULT,
  1191.             Result ? GetString(MSG_STRESULT_FAIL) : GetString(MSG_STRESULT_OK));
  1192.         if (Result)
  1193.             Dsk->DrvDat.Properties.AppendQFA = 0;
  1194.  
  1195.         if (CreateProtocol)
  1196.             {
  1197.             PostError(TRUE, MSGPRI_Info, GetString(MSG_QFAAPPEND_RESULT),
  1198.                 Result ? DecodeTapeError(Dsk, Line) : GetString(MSG_STRESULT_OK));
  1199.             }
  1200.  
  1201.         SetPropertyGadgets(&Dsk->DrvDat.Properties);
  1202.         Delay(100);
  1203.         }
  1204.  
  1205.  
  1206.     if (DataBlock)
  1207.         FreeVec(DataBlock);
  1208.  
  1209.     return TRUE;
  1210. }
  1211.  
  1212.  
  1213. static long TestQFAAppend(struct DiskFlags *Dsk, unsigned char *DataBlock)
  1214. {
  1215.     char Line[120];
  1216.     long Error;
  1217.  
  1218.     TapeRewind(Dsk->TapeReq);
  1219.  
  1220.     Error = TapeSpace(Dsk->TapeReq, 0, 3);        // Space To End Of Recording
  1221.     if (Error)
  1222.         return Error;
  1223.  
  1224.     memset(DataBlock, 0xaa, Dsk->DrvDat.BlockSize);
  1225.     Error = TapeWrite(Dsk->TapeReq, DataBlock, Dsk->DrvDat.BlockSize);
  1226.     if (Error && CreateProtocol)
  1227.         {
  1228.         PostError(TRUE, MSGPRI_Info, GetString(MSG_TAPEAPPENDWRITE_RESULT), DecodeTapeError(Dsk, Line));
  1229.         return Error;
  1230.         }
  1231.  
  1232.     TapeRewind(Dsk->TapeReq);
  1233.  
  1234.     Error = TapeSetDirectoryPartition(Dsk->TapeReq);
  1235.     if (Error && CreateProtocol)
  1236.         {
  1237.         PostError(TRUE, MSGPRI_Info, GetString(MSG_CHANGEPARTITION_RESULT), DecodeTapeError(Dsk, Line));
  1238.         return Error;
  1239.         }
  1240.  
  1241.     // jetzt einen Block in die Directory Partition schreiben
  1242.     memset(DataBlock, 0x55, Dsk->DrvDat.BlockSize);
  1243.     Error = TapeWrite(Dsk->TapeReq, DataBlock, Dsk->DrvDat.BlockSize);
  1244.     if (Error && CreateProtocol)
  1245.         {
  1246.         PostError(TRUE, MSGPRI_Info, GetString(MSG_TAPEAPPENDWRITEQFA_FAIL), DecodeTapeError(Dsk, Line));
  1247.         return Error;
  1248.         }
  1249.  
  1250.     TapeRewind(Dsk->TapeReq);
  1251.     TapeSetDataPartition(Dsk->TapeReq);
  1252.  
  1253.     return 0;
  1254. }
  1255.  
  1256.  
  1257. static BOOL CreateMountFile(struct DiskFlags *Dsk)
  1258. {
  1259.     BOOL is21;
  1260.     const char *OpenMode;
  1261.     FILE *fd;
  1262.     char FileName[FMSIZE];
  1263.  
  1264.     is21 = SysBase->LibNode.lib_Version > 36;
  1265.  
  1266.     if (is21)
  1267.         {
  1268.         char *InitialFileName;
  1269.         short ynResult;
  1270.  
  1271.         InitialFileName = GADSTRING(STGadgets[GDX_STTapeName]);
  1272.  
  1273.         do    {
  1274.             // Filename erfragen
  1275.             if (!StdFile(STWnd, GetString(MSG_MOUNTFILENAME_ASK), InitialFileName,
  1276.                     FileName, sizeof(FileName),
  1277.                     ASLFR_DoSaveMode, TRUE,
  1278.                     ASLFR_RejectIcons, TRUE,
  1279.                     ASLFR_DoPatterns, TRUE,
  1280.                     TAG_END))
  1281.                 {
  1282.                 return FALSE;
  1283.                 }
  1284.  
  1285.             OpenMode = "w";
  1286.  
  1287.             if (0 == access(FileName, F_OK))
  1288.                 {
  1289.                 // wenn es dieses File schon gibt: nachfragen!
  1290.                 ynResult = yesno(STWnd, GetString(MSG_REPLACE_MOUNTFILE), FileName);
  1291.                 }
  1292.             else
  1293.                 {
  1294.                 ynResult = *GetString(MSG_YES_SHORT);
  1295.                 }
  1296.             } while (ynResult != *GetString(MSG_YES_SHORT));
  1297.         }
  1298.     else
  1299.         {
  1300.         stccpy(FileName, "DEVS:MountList", sizeof(FileName));
  1301.         OpenMode = "a";
  1302.         }
  1303.  
  1304.     fd = fopen(FileName, OpenMode);
  1305.     if (fd)
  1306.         WriteMountList(fd, Dsk);
  1307.     else
  1308.         alarm(GetString(MSG_CANNOT_OPENFILE), Dsk->DOSName, GetIoErrText());
  1309. }
  1310.  
  1311.  
  1312. static BOOL WriteMountList(FILE *fd, const struct DiskFlags *Dsk)
  1313. {
  1314.     BOOL is21;
  1315.  
  1316.     is21 = SysBase->LibNode.lib_Version > 36;
  1317.  
  1318.     fputs("/* Backup & Restore Tape mount entry under 2.1 */\n", fd);
  1319.     fputs("\n", fd);
  1320.     fputs("/* Wichtig sind nur Name, \"Device\", \"Unit\", \"Flags\", \"Mask\"  und \"BufMemType\" */\n", fd);
  1321.     fputs("\n", fd);
  1322.     if (!is21)
  1323.         fprintf(fd, "%s:", Dsk->DOSName);
  1324.  
  1325.     fprintf(fd, "    Device     = %s\n", Dsk->DeviceName);
  1326.     fprintf(fd, "    Unit       = %ld", Dsk->Unit);
  1327.     fprintf(fd, "    Flags      = %ld\n", Dsk->DrvDat.Flags);
  1328.     fprintf(fd, "    GlobVec    = %ld\n", -1);
  1329.     fprintf(fd, "    DosType    = 0x%08lx\n", MAKE_ID('T','A','P','\0'));
  1330.     fprintf(fd, "    BufMemType = %ld\n", Dsk->DrvDat.BufMemType);
  1331.     fprintf(fd, "    Mask       = 0x%08lx\n", ~0);
  1332.     fprintf(fd, "    Activate   = %ld\n", 0);
  1333.  
  1334.     if (!is21)
  1335.         fputs("#\n\n", fd);
  1336.     else
  1337.         fclose(fd);
  1338.  
  1339.     return TRUE;
  1340. }
  1341.  
  1342.  
  1343. static BOOL MountTapeDrive(struct DiskFlags *Dsk)
  1344. {
  1345.     struct DosList *Device;
  1346.     struct DosList *dlist;
  1347.     struct FileSysStartupMsg *StartupMsg;
  1348.     struct DosEnvec *Env;
  1349.     char *Allocated, *AllPtr;
  1350.     char *DevName;
  1351.  
  1352.     if (NULL == Dsk)
  1353.         return FALSE;
  1354.  
  1355.     AllPtr = Allocated = AllocMem(strlen(Dsk->DeviceName) + 1 + 
  1356.             sizeof(struct DosEnvec) + sizeof(struct FileSysStartupMsg),
  1357.             MEMF_PUBLIC|MEMF_CLEAR);
  1358.     if (NULL == Allocated)
  1359.         return FALSE;
  1360.  
  1361.     DevName = AllPtr;
  1362.     strcpy(DevName, Dsk->DeviceName);
  1363.     AllPtr += strlen(Dsk->DeviceName) + 1;
  1364.  
  1365.     Env = (struct DosEnvec *) AllPtr;
  1366.     AllPtr += sizeof(*Env);
  1367.  
  1368.     StartupMsg = (struct FileSysStartupMsg *) AllPtr;
  1369.  
  1370.     while(1)
  1371.         {
  1372.         dlist = AttemptLockDosList(LDF_DEVICES|LDF_WRITE);
  1373.         // Account for DOS bug in V39 which may cause AttemptLockDosList
  1374.         // to return 1 instead of NULL                                             
  1375.         if (dlist != NULL && dlist != (struct DosList *) 1)
  1376.             break;
  1377.         // Can't lock the DOS list.  Wait a second and try again.
  1378.         Delay(50);
  1379.         }
  1380.     Device = FindDosEntry(dlist, Dsk->DOSName, LDF_DEVICES);
  1381.  
  1382.     if (Device)
  1383.         RemDosEntry(Device);
  1384.  
  1385.     UnLockDosList(LDF_DEVICES|LDF_WRITE);
  1386.  
  1387.     if(!Device && !(Device = MakeDosEntry(Dsk->DOSName, DLT_DEVICE)))
  1388.         {
  1389.         return FALSE;
  1390.         }
  1391.  
  1392.     Env->de_TableSize = DE_MASK;
  1393.     Env->de_SizeBlock = 512 / sizeof(long);        // in longwords: standard value is 128
  1394.     Env->de_SecOrg = 0;                // not used; must be 0
  1395.     Env->de_Surfaces = 1;                // # of heads (surfaces). drive specific
  1396.     Env->de_SectorPerBlock = 1;            // not used; must be 1
  1397.     Env->de_BlocksPerTrack = 1;            // blocks per track. drive specific
  1398.     Env->de_Reserved = 0;                // DOS reserved blocks at start of partition.
  1399.     Env->de_PreAlloc = 0;                // DOS reserved blocks at end of partition
  1400.     Env->de_Interleave = 0;                // usually 0
  1401.     Env->de_LowCyl = 0;                // starting cylinder. typically 0
  1402.     Env->de_HighCyl = 1;                // max cylinder. drive specific
  1403.     Env->de_NumBuffers = 10;            // Initial # DOS of buffers. 
  1404.     Env->de_BufMemType = Dsk->DrvDat.BufMemType;    // type of mem to allocate for buffers
  1405.     Env->de_MaxTransfer = 0x00ffffff;        // Max number of bytes to transfer at a time
  1406.     Env->de_Mask = ~0;                // Address Mask to block out certain memory
  1407.  
  1408.     StartupMsg->fssm_Unit = Dsk->Unit;
  1409.     StartupMsg->fssm_Device = MKBADDR(DevName);
  1410.     StartupMsg->fssm_Environ = MKBADDR(Env);
  1411.     StartupMsg->fssm_Flags = Dsk->DrvDat.Flags;
  1412.  
  1413.     Device->dol_misc.dol_handler.dol_Handler = NULL;
  1414.     Device->dol_misc.dol_handler.dol_StackSize = 8192;
  1415.     Device->dol_misc.dol_handler.dol_Priority = 0;
  1416.     Device->dol_misc.dol_handler.dol_Startup = MKBADDR(StartupMsg);
  1417.     Device->dol_misc.dol_handler.dol_SegList = NULL;
  1418.     Device->dol_misc.dol_handler.dol_GlobVec = (BPTR) -1;
  1419.  
  1420.     // Now we can own the volume by giving it our msgport
  1421.     Device->dol_Task = NULL;
  1422.  
  1423.     while (1)
  1424.         {
  1425.         dlist = AttemptLockDosList(LDF_DEVICES|LDF_WRITE);
  1426.         // Account for DOS bug in V39 which may cause AttemptLockDosList
  1427.         // to return 1 instead of NULL                                             
  1428.         if(dlist != NULL && dlist != (struct DosList *)1)
  1429.             break;
  1430.         // Oops, can't lock DOS list.  Wait 1 second and retry.
  1431.         Delay(50);
  1432.         }
  1433.     AddDosEntry(Device);
  1434.     UnLockDosList(LDF_DEVICES|LDF_WRITE);
  1435.  
  1436.     return TRUE;
  1437. }
  1438.  
  1439.  
  1440. static void FindDsk(const char *Device, short Unit)
  1441. {
  1442.     short n;
  1443.     
  1444.     for (n=0; n<NDisk; n++)
  1445.         {
  1446.         if (Disks[n].TapeReq && Unit == Disks[n].Unit && 0 == stricmp(Device, Disks[n].DeviceName))
  1447.             {
  1448.             strcpy(TapeDsk.DOSName, Disks[n].DOSName);
  1449.             break;
  1450.             }
  1451.         }
  1452. }
  1453.